/*
 * SIT_Splitter.c : split form into two parts (vertical or horizontal).
 *
 * Written by T.Pierron, Apr 2010.
 */

#include "SIT_P.h"
#include "graphics_P.h"
#include <stdio.h>

	TagList SplitterClass[] = {
		{ SIT_SuperClass,   NULL,           ___, SIT_INT,  (ULONG) WidgetClass },
		{ SIT_HandleStyle,  "handleStyle",  _SG, SIT_INT,  OFFSET(SIT_Splitter, sp_Style) },
		{ SIT_HorizSplit,   "horizSplit",   __G, SIT_BOOL, OFFSET(SIT_Splitter, sp_Horiz) },
		{ SIT_LiveResize,   "liveResize",   _SG, SIT_BOOL, OFFSET(SIT_Splitter, sp_LiveResize) },
		{ SIT_MinSizeLeft,  "minSizeLeft",  _SG, SIT_INT,  OFFSET(SIT_Splitter, sp_MinSizeLeft) },
		{ SIT_MinSizeRight, "minSizeRight", _SG, SIT_INT,  OFFSET(SIT_Splitter, sp_MinSizeRight) },
		{ SIT_TagEnd }
	};

	static uint8_t holes_data[] =
		"\240\240\240'''\240\240\240   "
		"JJJ\223\223\223\262\262\262   "
		"\223\223\223\377\377\377\377\377\377   ";

	static WORD dotPatternBmp[] =
	{
		0x00aa, 0x0055, 0x00aa, 0x0055,
		0x00aa, 0x0055, 0x00aa, 0x0055
	};

	static BITMAPINFOHEADER holes_bi = {sizeof holes_bi, 3, -3, 1, 24};

static int SIT_MeasureSplitter(SIT_Widget w, APTR cd, APTR ud)
{
	SIT_Splitter s = (APTR) w;
	SIZE *       ret = cd;
	if (s->sp_Horiz) ret->cy = 5;
	else             ret->cx = 5;
	return 1;
}

static int SIT_SplitterPaint(SIT_Widget w, APTR cd, APTR ud)
{
	SIT_Splitter s = (APTR) w;
	RECT rect;
	LONG * c;
	GC gc = cd;
	int i;

	#define	box (&w->sw_Box)
	if (s->sp_Horiz)
	{
		rect.left   = (box->width  - box->x - 14) >> 1;
		rect.top    = (box->height - box->y - 3) >> 1;
		rect.right  = rect.left + 15;
		rect.bottom = rect.top  + 4;
		i = BF_TOP | BF_BOTTOM;
	}
	else
	{
		rect.left   = (box->width  - box->x - 3) >> 1;
		rect.top    = (box->height - box->y - 14) >> 1;
		rect.right  = rect.left + 4;
		rect.bottom = rect.top  + 15;
		i = BF_LEFT | BF_RIGHT;
	}
	#undef box
	switch (s->sp_Style) {
	case SITV_FlatStyle:
		return 0;
	case SITV_RoundHoles:
		c = &rect.top - s->sp_Horiz;
		for (i = 0, (*c) ++; i < 3; i ++, (*c) += 4)
			SetDIBitsToDevice(gc->device, rect.left, rect.top, 3, 3, 0, 0, 0, 3, holes_data,
				(LPBITMAPINFO) &holes_bi, DIB_RGB_COLORS);
		break;
	case SITV_VerticalBar:
		DrawEdge(gc->device, &rect, EDGE_ETCHED, i);
	}
	return 1;
}

static void SIT_ResizeSplitter(SIT_Splitter s)
{
	SIT_Attach * left = s->super.sw_Attachment + s->sp_Horiz;
	SIT_Widget   w;
	int          pos = s->sp_CurPos;

	if (left->sa_Type == SITV_AttachWidget)
	{
		SIT_Widget   arg   = (APTR) left->sa_Arg;
		SIT_Attach * right = arg->sw_Attachment + 2 + s->sp_Horiz;

		right->sa_Type   = SITV_AttachWidget;
		right->sa_Offset = left->sa_Offset;
		right->sa_Arg    = (ULONG) s;
	}

	w = s->super.sw_Parent;
	pos -= w->sw_Margins[s->sp_Horiz];

	if (s->super.sw_Flags & (s->sp_Horiz ? SITF_FixedY : SITF_FixedX))
		left->sa_Offset = 0, (&s->super.sw_Fixed.x)[s->sp_Horiz] = pos;
	else
		left->sa_Offset = pos;
	left->sa_Type = SITV_AttachFixed;
	left->sa_Arg = 0;

	while (w && w->sw_Type != SIT_DIALOG) w = w->sw_Parent;

	SIT_LayoutWidgets(w, KeepDialogSize);
	SIT_MoveWidgets(w);
}

static void SIT_DrawSplitterFrame(SIT_Splitter s)
{
	Rect * box = &s->super.sw_Box;
	int    w   = box->width  - box->x;
	int    h   = box->height - box->y;

	if (! s->sp_WndHDC) {
		RECT parent, rect;
		HBITMAP hbm;
		/* Can't use GetDC because content will be clipped by WS_CLIPCHILDREN */
		s->sp_WndHDC = GetWindowDC(s->super.sw_Parent->sw_Handle);
		//GetDCEx(s->super.sw_Parent->sw_Handle, NULL, DCX_WINDOW | 0x10000);
		/* Offset DC from size of non-client area */
		GetWindowRect(s->super.sw_Parent->sw_Handle, &parent);
		GetWindowRect(s->super.sw_Handle, &rect);
		SetViewportOrgEx(s->sp_WndHDC, rect.left - parent.left - box->x,
			rect.top - parent.top - box->y, NULL);

		hbm = CreateBitmap(8, 8, 1, 1, dotPatternBmp);
		s->sp_Bg = CreatePatternBrush(hbm);
		DeleteObject(hbm);
	}

	HBRUSH old = SelectObject(s->sp_WndHDC, s->sp_Bg);

	if (s->sp_Horiz)
		PatBlt(s->sp_WndHDC, box->x, s->sp_CurPos, w, h, PATINVERT);
	else
		PatBlt(s->sp_WndHDC, s->sp_CurPos, box->y, w, h, PATINVERT);

	SelectObject(s->sp_WndHDC, old);
}

static int SIT_SplitterMove(SIT_Widget w, APTR cd, APTR ud)
{
	SIT_OnMouse * msg = cd;
	SIT_Splitter  s = (APTR) w;

	if (msg->button == 0)
	{
		POINT pt;
		int pos, max;
		switch (msg->state) {
		case SITOM_ButtonPressed:
			pt.x = msg->x;
			pt.y = msg->y;
			ClientToScreen(w->sw_Handle, &pt);
			s->sp_Init.x = pt.x;
			s->sp_Init.y = pt.y;
			s->sp_CurPos = (&w->sw_Box.x)[s->sp_Horiz];
			if (! s->sp_LiveResize) SIT_DrawSplitterFrame(s);
			return 1;
		case SITOM_CaptureMove:
			pt.x = msg->x;
			pt.y = msg->y;
			ClientToScreen(w->sw_Handle, &pt);
			pos = s->sp_CurPos + (&pt.x)[s->sp_Horiz] - (&s->sp_Init.x)[s->sp_Horiz];
			w   = w->sw_Parent;
			max = (&w->sw_Box.width)[s->sp_Horiz] - (&w->sw_Box.x)[s->sp_Horiz] -
			      s->sp_MinSizeRight - 3;
			if (pos < s->sp_MinSizeLeft) pos = s->sp_MinSizeLeft;
			if (pos > max) pos = max;
			if (pos != s->sp_CurPos)
			{
				if (! s->sp_LiveResize)
				{
					SIT_DrawSplitterFrame(s); s->sp_CurPos = pos;
					SIT_DrawSplitterFrame(s);
				}
				else s->sp_CurPos = pos, SIT_ResizeSplitter(s);
				s->sp_Init.x = pt.x;
				s->sp_Init.y = pt.y;
			}
			break;
		case SITOM_ButtonReleased:
			if (s->sp_WndHDC)
			{
				SIT_DrawSplitterFrame(s);
				ReleaseDC(s->super.sw_Parent->sw_Handle, s->sp_WndHDC);
				DeleteObject(s->sp_Bg);
				SIT_ResizeSplitter(s);
				s->sp_WndHDC = NULL;
				s->sp_Bg = NULL;
			}
			break;
		}
	}
	return 0;
}

BOOL SIT_CreateSplitter(SIT_Widget w, va_list args)
{
	SIT_Splitter split = (APTR) w;
	int          style = WS_CHILD;
	HWND         hwnd;
	WCHAR        clsName[48];

	split->sp_Init.x = -1;
	split->sp_Init.y = -1;
	w->sw_OptimalWidth = SIT_MeasureSplitter;

	SIT_ParseTags(w, args, w->sw_Class = SplitterClass);
	SIT_RegisterClass(w, clsName, CS_HREDRAW | CS_VREDRAW, split->sp_Horiz ? IDC_SIZENS :
		IDC_SIZEWE, NULL);

	if (IsVisible(w)) style |= WS_VISIBLE;
	if (HAS_TAB(w))   style |= WS_TABSTOP;

	/* Create Win32 control, pos and dim will be set later */
	hwnd = w->sw_Handle = CreateWindow(clsName, w->sw_Name, style, 0, 0, 10, 10,
		SIT_GetContainer(w), (HMENU) MAKE_ID(w), instance, NULL);

	if (hwnd == NULL) return FALSE;
	SIT_SetDefaultFont(w);
	SIT_AddCallback(w, SITE_OnPaint,     SIT_SplitterPaint, NULL);
	SIT_AddCallback(w, SITE_OnClick,     SIT_SplitterMove, NULL);
	SIT_AddCallback(w, SITE_OnMouseMove, SIT_SplitterMove, NULL);

	/* Keep track of class inside callback */
	SetProp(hwnd, sit_class, (HANDLE) w);

	return TRUE;
}
